import java.sql.*;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.UUID;
import java.time.format.DateTimeParseException;

public class CinemaSystem5 {
    public static void main(String[] args) {
        CinemaSystem5 cinema = new CinemaSystem5();
        cinema.start();
    }

    // 数据库连接工具类
    static class DatabaseConnection {
        public static Connection connect() {
            try {
                Class.forName("org.sqlite.JDBC");
                return DriverManager.getConnection("jdbc:sqlite:cinema_system.db");
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    // 用户管理数据库操作类
    static class UserManager {
        public void addUser(User user) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "INSERT INTO users (user_id, username, password, register_time, phone, type) VALUES (?, ?, ?, ?, ?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, user.getUserId());
                pstmt.setString(2, user.getUsername());
                pstmt.setString(3, user.getPassword());
                pstmt.setString(4, user.getRegisterTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                pstmt.setString(5, user.getPhone());
                pstmt.setString(6, user.getType());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public User getUser(String username) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM users WHERE username = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, username);
                ResultSet rs = pstmt.executeQuery();

                if (rs.next()) {
                    return new User(
                            rs.getString("user_id"),
                            rs.getString("username"),
                            rs.getString("password"),
                            LocalDateTime.parse(rs.getString("register_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                            rs.getString("phone"),
                            rs.getString("type")
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }

        public List<User> listAllUsers() {
            List<User> users = new ArrayList<>();
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM users";
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql);

                while (rs.next()) {
                    users.add(new User(
                            rs.getString("user_id"),
                            rs.getString("username"),
                            rs.getString("password"),
                            LocalDateTime.parse(rs.getString("register_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                            rs.getString("phone"),
                            rs.getString("type")
                    ));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return users;
        }

        public void deleteUser(String username) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "DELETE FROM users WHERE username = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, username);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void updateUser(User user) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "UPDATE users SET phone = ?, type = ? WHERE username = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, user.getPhone());
                pstmt.setString(2, user.getType());
                pstmt.setString(3, user.getUsername());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void initializeUserTable() {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "CREATE TABLE IF NOT EXISTS users (" +
                        "user_id TEXT PRIMARY KEY, " +
                        "username TEXT UNIQUE, " +
                        "password TEXT, " +
                        "register_time TEXT, " +
                        "phone TEXT, " +
                        "type TEXT)";
                Statement stmt = conn.createStatement();
                stmt.execute(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 电影管理数据库操作类
    static class MovieManager {
        public void addMovie(Movie movie) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "INSERT INTO movies (movie_id, title, director, stars, description, duration, rating) VALUES (?, ?, ?, ?, ?, ?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, movie.getMovieId());
                pstmt.setString(2, movie.getTitle());
                pstmt.setString(3, movie.getDirector());
                pstmt.setString(4, String.join(",", movie.getStars()));
                pstmt.setString(5, movie.getDescription());
                pstmt.setInt(6, movie.getDuration());
                pstmt.setDouble(7, movie.getRating());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public Movie getMovie(String movieId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM movies WHERE movie_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, movieId);
                ResultSet rs = pstmt.executeQuery();

                if (rs.next()) {
                    return new Movie(
                            rs.getString("movie_id"),
                            rs.getString("title"),
                            rs.getString("director"),
                            rs.getString("stars").split(","),
                            rs.getString("description"),
                            rs.getInt("duration"),
                            rs.getDouble("rating")
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }

        public List<Movie> listAllMovies() {
            List<Movie> movies = new ArrayList<>();
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM movies";
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql);

                while (rs.next()) {
                    movies.add(new Movie(
                            rs.getString("movie_id"),
                            rs.getString("title"),
                            rs.getString("director"),
                            rs.getString("stars").split(","),
                            rs.getString("description"),
                            rs.getInt("duration"),
                            rs.getDouble("rating")
                    ));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return movies;
        }

        public void deleteMovie(String movieId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "DELETE FROM movies WHERE movie_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, movieId);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void updateMovie(Movie movie) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "UPDATE movies SET title = ?, director = ?, stars = ?, description = ?, duration = ?, rating = ? WHERE movie_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, movie.getTitle());
                pstmt.setString(2, movie.getDirector());
                pstmt.setString(3, String.join(",", movie.getStars()));
                pstmt.setString(4, movie.getDescription());
                pstmt.setInt(5, movie.getDuration());
                pstmt.setDouble(6, movie.getRating());
                pstmt.setString(7, movie.getMovieId());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void initializeMovieTable() {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "CREATE TABLE IF NOT EXISTS movies (" +
                        "movie_id TEXT PRIMARY KEY, " +
                        "title TEXT, " +
                        "director TEXT, " +
                        "stars TEXT, " +
                        "description TEXT, " +
                        "duration INTEGER, " +
                        "rating REAL)";
                Statement stmt = conn.createStatement();
                stmt.execute(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 放映场次管理数据库操作类
    static class ScreeningManager {
        private Map<String, ScreeningHall> halls;
        private MovieManager movieManager;

        public ScreeningManager(Map<String, ScreeningHall> halls, MovieManager movieManager) {
            this.halls = halls;
            this.movieManager = movieManager;
        }

        public void addScreening(Screening screening) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "INSERT INTO screenings (screening_id, movie_id, hall_name, start_time, price, cancelled) VALUES (?, ?, ?, ?, ?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, screening.getScreeningId());
                pstmt.setString(2, screening.getMovie().getMovieId());
                pstmt.setString(3, screening.getHall().getHallName());
                pstmt.setString(4, screening.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                pstmt.setDouble(5, screening.getPrice());
                pstmt.setBoolean(6, screening.isCancelled());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public Screening getScreening(String screeningId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM screenings WHERE screening_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, screeningId);
                ResultSet rs = pstmt.executeQuery();

                if (rs.next()) {
                    Movie movie = movieManager.getMovie(rs.getString("movie_id"));
                    ScreeningHall hall = halls.get(rs.getString("hall_name"));
                    return new Screening(
                            rs.getString("screening_id"),
                            movie,
                            hall,
                            LocalDateTime.parse(rs.getString("start_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                            rs.getDouble("price"),
                            rs.getBoolean("cancelled")
                    );
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }

        public List<Screening> listAllScreenings() {
            List<Screening> screenings = new ArrayList<>();
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM screenings";
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql);

                while (rs.next()) {
                    Movie movie = movieManager.getMovie(rs.getString("movie_id"));
                    ScreeningHall hall = halls.get(rs.getString("hall_name"));
                    screenings.add(new Screening(
                            rs.getString("screening_id"),
                            movie,
                            hall,
                            LocalDateTime.parse(rs.getString("start_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME),
                            rs.getDouble("price"),
                            rs.getBoolean("cancelled")
                    ));
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return screenings;
        }

        public void deleteScreening(String screeningId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "DELETE FROM screenings WHERE screening_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, screeningId);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void updateScreening(Screening screening) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "UPDATE screenings SET movie_id = ?, hall_name = ?, start_time = ?, price = ?, cancelled = ? WHERE screening_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, screening.getMovie().getMovieId());
                pstmt.setString(2, screening.getHall().getHallName());
                pstmt.setString(3, screening.getStartTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                pstmt.setDouble(4, screening.getPrice());
                pstmt.setBoolean(5, screening.isCancelled());
                pstmt.setString(6, screening.getScreeningId());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void initializeScreeningTable() {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "CREATE TABLE IF NOT EXISTS screenings (" +
                        "screening_id TEXT PRIMARY KEY, " +
                        "movie_id TEXT, " +
                        "hall_name TEXT, " +
                        "start_time TEXT, " +
                        "price REAL, " +
                        "cancelled BOOLEAN)";
                Statement stmt = conn.createStatement();
                stmt.execute(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public ScreeningHall getHall(String hallName) {
            return halls.get(hallName);
        }
    }

    // 票务管理数据库操作类
    static class TicketManager {
        private ScreeningManager screeningManager;

        public void setScreeningManager(ScreeningManager screeningManager) {
            this.screeningManager = screeningManager;
        }

        public void addTicket(Ticket ticket) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "INSERT INTO tickets (ticket_id, screening_id, seat_info, price, purchase_time, refunded, refund_time, refunded_amount) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, ticket.getTicketId());
                pstmt.setString(2, ticket.getScreening().getScreeningId());
                pstmt.setString(3, ticket.getSeatInfo());
                pstmt.setDouble(4, ticket.getPrice());
                pstmt.setString(5, ticket.getPurchaseTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                pstmt.setBoolean(6, ticket.isRefunded());
                pstmt.setString(7, ticket.getRefundTime() != null ? ticket.getRefundTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
                pstmt.setDouble(8, ticket.getRefundedAmount());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public Ticket getTicket(String ticketId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM tickets WHERE ticket_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, ticketId);
                ResultSet rs = pstmt.executeQuery();

                if (rs.next()) {
                    Screening screening = screeningManager.getScreening(rs.getString("screening_id"));
                    LocalDateTime refundTime = null;
                    if (rs.getString("refund_time") != null) {
                        refundTime = LocalDateTime.parse(rs.getString("refund_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                    }

                    Ticket ticket = new Ticket(
                            rs.getString("ticket_id"),
                            screening,
                            rs.getString("seat_info"),
                            rs.getDouble("price")
                    );
                    ticket.setRefunded(rs.getBoolean("refunded"));
                    ticket.setRefundTime(refundTime);
                    ticket.setRefundedAmount(rs.getDouble("refunded_amount"));
                    ticket.setPurchaseTime(LocalDateTime.parse(rs.getString("purchase_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME));

                    return ticket;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }

        public List<Ticket> listAllTickets() {
            List<Ticket> tickets = new ArrayList<>();
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "SELECT * FROM tickets";
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery(sql);

                while (rs.next()) {
                    Screening screening = screeningManager.getScreening(rs.getString("screening_id"));
                    LocalDateTime refundTime = null;
                    if (rs.getString("refund_time") != null) {
                        refundTime = LocalDateTime.parse(rs.getString("refund_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME);
                    }

                    Ticket ticket = new Ticket(
                            rs.getString("ticket_id"),
                            screening,
                            rs.getString("seat_info"),
                            rs.getDouble("price")
                    );
                    ticket.setRefunded(rs.getBoolean("refunded"));
                    ticket.setRefundTime(refundTime);
                    ticket.setRefundedAmount(rs.getDouble("refunded_amount"));
                    ticket.setPurchaseTime(LocalDateTime.parse(rs.getString("purchase_time"), DateTimeFormatter.ISO_LOCAL_DATE_TIME));

                    tickets.add(ticket);
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return tickets;
        }

        public void deleteTicket(String ticketId) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "DELETE FROM tickets WHERE ticket_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, ticketId);
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void updateTicket(Ticket ticket) {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "UPDATE tickets SET refunded = ?, refund_time = ?, refunded_amount = ? WHERE ticket_id = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setBoolean(1, ticket.isRefunded());
                pstmt.setString(2, ticket.getRefundTime() != null ? ticket.getRefundTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null);
                pstmt.setDouble(3, ticket.getRefundedAmount());
                pstmt.setString(4, ticket.getTicketId());
                pstmt.executeUpdate();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        public void initializeTicketTable() {
            try (Connection conn = DatabaseConnection.connect()) {
                String sql = "CREATE TABLE IF NOT EXISTS tickets (" +
                        "ticket_id TEXT PRIMARY KEY, " +
                        "screening_id TEXT, " +
                        "seat_info TEXT, " +
                        "price REAL, " +
                        "purchase_time TEXT, " +
                        "refunded BOOLEAN, " +
                        "refund_time TEXT, " +
                        "refunded_amount REAL)";
                Statement stmt = conn.createStatement();
                stmt.execute(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    // 用户类
    static class User {
        private String userId;
        private String username;
        private String password;
        private LocalDateTime registerTime;
        private String phone;
        private String type;

        public User(String userId, String username, String password, LocalDateTime registerTime, String phone, String type) {
            this.userId = userId;
            this.username = username;
            this.password = password;
            this.registerTime = registerTime;
            this.phone = phone;
            this.type = type;
        }

        // Getters and Setters
        public String getUserId() { return userId; }
        public String getUsername() { return username; }
        public String getPassword() { return password; }
        public LocalDateTime getRegisterTime() { return registerTime; }
        public String getPhone() { return phone; }
        public String getType() { return type; }

        public void setUserId(String userId) { this.userId = userId; }
        public void setUsername(String username) { this.username = username; }
        public void setPassword(String password) { this.password = password; }
        public void setRegisterTime(LocalDateTime registerTime) { this.registerTime = registerTime; }
        public void setPhone(String phone) { this.phone = phone; }
        public void setType(String type) { this.type = type; }
    }

    // 电影类
    static class Movie {
        private String movieId;
        private String title;
        private String director;
        private String[] stars;
        private String description;
        private int duration;
        private double rating;

        public Movie(String movieId, String title, String director, String[] stars, String description, int duration, double rating) {
            this.movieId = movieId;
            this.title = title;
            this.director = director;
            this.stars = stars;
            this.description = description;
            this.duration = duration;
            this.rating = rating;
        }

        // Getters and Setters
        public String getMovieId() { return movieId; }
        public String getTitle() { return title; }
        public String getDirector() { return director; }
        public String[] getStars() { return stars; }
        public String getDescription() { return description; }
        public int getDuration() { return duration; }
        public double getRating() { return rating; }

        public void setMovieId(String movieId) { this.movieId = movieId; }
        public void setTitle(String title) { this.title = title; }
        public void setDirector(String director) { this.director = director; }
        public void setStars(String[] stars) { this.stars = stars; }
        public void setDescription(String description) { this.description = description; }
        public void setDuration(int duration) { this.duration = duration; }
        public void setRating(double rating) { this.rating = rating; }
    }

    // 放映厅类
    static class ScreeningHall {
        private String hallName;
        private int rows;
        private int cols;
        private Seat[][] seats;

        public ScreeningHall(String name, int rows, int cols) {
            this.hallName = name;
            this.rows = rows;
            this.cols = cols;
            initializeSeats();
        }

        private void initializeSeats() {
            seats = new Seat[rows][cols];
            for (int i = 0; i < rows; i++) {
                for (int j = 0; j < cols; j++) {
                    seats[i][j] = new Seat(i, j);
                }
            }
        }

        // Getters and Setters
        public String getHallName() { return hallName; }
        public int getRows() { return rows; }
        public int getCols() { return cols; }

        public Seat getSeat(int row, int col) {
            if (row < 0 || row >= rows || col < 0 || col >= cols) {
                throw new IllegalArgumentException("Seat out of bounds");
            }
            return seats[row][col];
        }

        public void displaySeatMap() {
            System.out.println("\nSeat Map for " + hallName + ":");
            System.out.print("   ");
            for (int j = 0; j < cols; j++) {
                System.out.printf("%2d ", j + 1);
            }
            System.out.println();

            for (int i = 0; i < rows; i++) {
                System.out.printf("%2d ", i + 1);
                for (int j = 0; j < cols; j++) {
                    System.out.print(seats[i][j].isAvailable() ? " O " : " X ");
                }
                System.out.println();
            }
            System.out.println("O: Available  X: Occupied");
        }

        class Seat {
            private int row;
            private int col;
            private boolean available;

            public Seat(int row, int col) {
                this.row = row;
                this.col = col;
                this.available = true;
            }

            // Getters and Setters
            public int getRow() { return row; }
            public int getCol() { return col; }
            public boolean isAvailable() { return available; }
            public void setAvailable(boolean available) { this.available = available; }
        }
    }

    // 放映场次类
    static class Screening {
        private String screeningId;
        private Movie movie;
        private ScreeningHall hall;
        private LocalDateTime startTime;
        private double price;
        private boolean cancelled;

        public Screening(String screeningId, Movie movie, ScreeningHall hall, LocalDateTime startTime, double price, boolean cancelled) {
            this.screeningId = screeningId;
            this.movie = movie;
            this.hall = hall;
            this.startTime = startTime;
            this.price = price;
            this.cancelled = cancelled;
        }

        // Getters and Setters
        public String getScreeningId() { return screeningId; }
        public Movie getMovie() { return movie; }
        public ScreeningHall getHall() { return hall; }
        public LocalDateTime getStartTime() { return startTime; }
        public double getPrice() { return price; }
        public boolean isCancelled() { return cancelled; }

        public void setScreeningId(String screeningId) { this.screeningId = screeningId; }
        public void setMovie(Movie movie) { this.movie = movie; }
        public void setHall(ScreeningHall hall) { this.hall = hall; }
        public void setStartTime(LocalDateTime startTime) { this.startTime = startTime; }
        public void setPrice(double price) { this.price = price; }
        public void setCancelled(boolean cancelled) { this.cancelled = cancelled; }
    }

    // 电影票类
    static class Ticket {
        private String ticketId;
        private Screening screening;
        private String seatInfo;
        private double price;
        private LocalDateTime purchaseTime;
        private boolean refunded;
        private LocalDateTime refundTime;
        private double refundedAmount;

        public Ticket(String ticketId, Screening screening, String seatInfo, double price) {
            this.ticketId = ticketId;
            this.screening = screening;
            this.seatInfo = seatInfo;
            this.price = price;
            this.purchaseTime = LocalDateTime.now();
            this.refunded = false;
            this.refundedAmount = 0;
        }

        // Getters and Setters
        public String getTicketId() { return ticketId; }
        public Screening getScreening() { return screening; }
        public String getSeatInfo() { return seatInfo; }
        public double getPrice() { return price; }
        public LocalDateTime getPurchaseTime() { return purchaseTime; }
        public boolean isRefunded() { return refunded; }
        public LocalDateTime getRefundTime() { return refundTime; }
        public double getRefundedAmount() { return refundedAmount; }

        public void setTicketId(String ticketId) { this.ticketId = ticketId; }
        public void setScreening(Screening screening) { this.screening = screening; }
        public void setSeatInfo(String seatInfo) { this.seatInfo = seatInfo; }
        public void setPrice(double price) { this.price = price; }
        public void setPurchaseTime(LocalDateTime purchaseTime) { this.purchaseTime = purchaseTime; }
        public void setRefunded(boolean refunded) { this.refunded = refunded; }
        public void setRefundTime(LocalDateTime refundTime) { this.refundTime = refundTime; }
        public void setRefundedAmount(double refundedAmount) { this.refundedAmount = refundedAmount; }
    }

    // 管理员类
    static class Admin extends User {
        public Admin(String userId, String username, String password, LocalDateTime registerTime, String phone) {
            super(userId, username, password, registerTime, phone, "ADMIN");
        }
    }

    // 经理类
    static class Manager extends User {
        public Manager(String userId, String username, String password, LocalDateTime registerTime, String phone) {
            super(userId, username, password, registerTime, phone, "MANAGER");
        }
    }

    // 前台类
    static class FrontDesk extends User {
        public FrontDesk(String userId, String username, String password, LocalDateTime registerTime, String phone) {
            super(userId, username, password, registerTime, phone, "FRONT_DESK");
        }
    }

    private UserManager userManager;
    private MovieManager movieManager;
    private ScreeningManager screeningManager;
    private TicketManager ticketManager;
    private User currentUser;
    private Scanner scanner;
    private Map<String, ScreeningHall> halls;

    public CinemaSystem5() {
        userManager = new UserManager();
        movieManager = new MovieManager();
        ticketManager = new TicketManager();

        halls = new HashMap<>();
        halls.put("黄金厅", new ScreeningHall("黄金厅", 8, 10));
        halls.put("白银厅", new ScreeningHall("白银厅", 10, 12));
        halls.put("翡翠厅", new ScreeningHall("翡翠厅", 7, 8));
        halls.put("钻石厅", new ScreeningHall("钻石厅", 7, 8));
        halls.put("宝石厅", new ScreeningHall("宝石厅", 8, 9));

        screeningManager = new ScreeningManager(halls, movieManager);
        ticketManager.setScreeningManager(screeningManager);
        scanner = new Scanner(System.in);
    }

    public void start() {
        userManager.initializeUserTable();
        movieManager.initializeMovieTable();
        screeningManager.initializeScreeningTable();
        ticketManager.initializeTicketTable();

        if (userManager.getUser("admin") == null) {
            userManager.addUser(new Admin("ADM001", "admin", "e99a18c428cb38d5f260853678922901", LocalDateTime.now(), "13800000000"));
        }

        while (true) {
            System.out.println("\n===== 万东影院管理系统 =====");
            System.out.println("1. 登录");
            System.out.println("2. 退出系统");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        login();
                        break;
                    case 2:
                        System.out.println("系统已退出");
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void login() {
        System.out.print("用户名: ");
        String username = scanner.nextLine();
        System.out.print("密码: ");
        String password = scanner.nextLine();

        currentUser = userManager.getUser(username);
        if (currentUser == null || !currentUser.getPassword().equals(password)) {
            System.out.println("用户名或密码错误");
            return;
        }

        if (currentUser.getType().equals("ADMIN")) {
            showAdminMenu();
        } else if (currentUser.getType().equals("MANAGER")) {
            showManagerMenu();
        } else if (currentUser.getType().equals("FRONT_DESK")) {
            showFrontDeskMenu();
        }
    }

    private void showAdminMenu() {
        while (true) {
            System.out.println("\n===== 管理员菜单 =====");
            System.out.println("1. 密码管理");
            System.out.println("2. 用户管理");
            System.out.println("3. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        adminPasswordMenu();
                        break;
                    case 2:
                        userManagementMenu();
                        break;
                    case 3:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void userManagementMenu() {
        while (true) {
            System.out.println("\n--- 用户管理 ---");
            System.out.println("1. 列出所有用户");
            System.out.println("2. 添加用户");
            System.out.println("3. 删除用户");
            System.out.println("4. 查询用户");
            System.out.println("5. 修改用户");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        List<User> users = userManager.listAllUsers();
                        System.out.println("\n用户列表:");
                        for (User user : users) {
                            System.out.println("用户名: " + user.getUsername() + ", 类型: " + user.getType());
                        }
                        break;
                    case 2:
                        System.out.print("用户ID: ");
                        String userId = scanner.nextLine();
                        System.out.print("用户名: ");
                        String username = scanner.nextLine();
                        System.out.print("密码: ");
                        String password = scanner.nextLine();
                        System.out.print("手机号: ");
                        String phone = scanner.nextLine();
                        System.out.print("类型 (ADMIN/MANAGER/FRONT_DESK): ");
                        String type = scanner.nextLine();
                        userManager.addUser(new User(userId, username, password, LocalDateTime.now(), phone, type));
                        System.out.println("用户添加成功");
                        break;
                    case 3:
                        System.out.print("输入要删除的用户名: ");
                        String delUsername = scanner.nextLine();
                        userManager.deleteUser(delUsername);
                        System.out.println("用户删除成功");
                        break;
                    case 4:
                        System.out.print("输入查询用户名: ");
                        String queryUsername = scanner.nextLine();
                        User user = userManager.getUser(queryUsername);
                        if (user != null) {
                            System.out.println("用户名: " + user.getUsername() + ", 类型: " + user.getType());
                        } else {
                            System.out.println("用户不存在");
                        }
                        break;
                    case 5:
                        System.out.print("输入要修改的用户名: ");
                        String updateUsername = scanner.nextLine();
                        User existingUser = userManager.getUser(updateUsername);
                        if (existingUser == null) {
                            System.out.println("用户不存在");
                            break;
                        }
                        System.out.print("新手机号: ");
                        String newPhone = scanner.nextLine();
                        System.out.print("新类型 (ADMIN/MANAGER/FRONT_DESK): ");
                        String newType = scanner.nextLine();
                        User newUser = new User(
                                existingUser.getUserId(),
                                updateUsername,
                                existingUser.getPassword(),
                                existingUser.getRegisterTime(),
                                newPhone,
                                newType
                        );
                        userManager.updateUser(newUser);
                        System.out.println("用户信息更新成功");
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void adminPasswordMenu() {
        System.out.println("\n--- 密码管理 ---");
        System.out.println("1. 修改自身密码");
        System.out.println("2. 重置用户密码");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    System.out.print("输入新密码: ");
                    String newPass = scanner.nextLine();
                    currentUser.setPassword(newPass);
                    userManager.updateUser(currentUser);
                    System.out.println("密码修改成功");
                    break;
                case 2:
                    System.out.print("输入要重置的用户名: ");
                    String username = scanner.nextLine();
                    User user = userManager.getUser(username);
                    if (user != null) {
                        user.setPassword("123456");
                        userManager.updateUser(user);
                        System.out.println("密码已重置为123456");
                    } else {
                        System.out.println("用户不存在");
                    }
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        }
    }

    private void showManagerMenu() {
        while (true) {
            System.out.println("\n===== 经理菜单 =====");
            System.out.println("1. 密码管理");
            System.out.println("2. 影片管理");
            System.out.println("3. 排片管理");
            System.out.println("4. 查看销售数据");
            System.out.println("5. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        managerPasswordMenu();
                        break;
                    case 2:
                        movieManagementMenu();
                        break;
                    case 3:
                        screeningManagementMenu();
                        break;
                    case 4:
                        salesReportMenu();
                        break;
                    case 5:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void managerPasswordMenu() {
        System.out.println("\n--- 密码管理 ---");
        System.out.println("1. 修改自身密码");
        System.out.println("2. 重置前台密码");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    System.out.print("输入新密码: ");
                    String newPass = scanner.nextLine();
                    currentUser.setPassword(newPass);
                    userManager.updateUser(currentUser);
                    System.out.println("密码修改成功");
                    break;
                case 2:
                    System.out.print("输入要重置的前台用户名: ");
                    String username = scanner.nextLine();
                    User user = userManager.getUser(username);
                    if (user != null && user.getType().equals("FRONT_DESK")) {
                        user.setPassword("123456");
                        userManager.updateUser(user);
                        System.out.println("密码已重置为123456");
                    } else {
                        System.out.println("用户不存在或不是前台用户");
                    }
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        }
    }

    private void movieManagementMenu() {
        while (true) {
            System.out.println("\n--- 影片管理 ---");
            System.out.println("1. 列出所有影片");
            System.out.println("2. 添加影片");
            System.out.println("3. 修改影片");
            System.out.println("4. 删除影片");
            System.out.println("5. 查询影片");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        List<Movie> movies = movieManager.listAllMovies();
                        System.out.println("\n影片列表:");
                        for (Movie movie : movies) {
                            System.out.println("ID: " + movie.getMovieId() + ", 片名: " + movie.getTitle() + ", 导演: " + movie.getDirector());
                        }
                        break;
                    case 2:
                        System.out.print("片名: ");
                        String title = scanner.nextLine();
                        System.out.print("导演: ");
                        String director = scanner.nextLine();
                        System.out.print("主演(用逗号分隔): ");
                        String[] stars = scanner.nextLine().split(",");
                        System.out.print("剧情简介: ");
                        String description = scanner.nextLine();
                        System.out.print("时长(分钟): ");
                        int duration = Integer.parseInt(scanner.nextLine());
                        System.out.print("评分(0-10): ");
                        double rating = Double.parseDouble(scanner.nextLine());
                        movieManager.addMovie(new Movie(UUID.randomUUID().toString(), title, director, stars, description, duration, rating));
                        System.out.println("影片添加成功");
                        break;
                    case 3:
                        System.out.print("输入要修改的电影ID: ");
                        String movieId = scanner.nextLine();
                        Movie movie = movieManager.getMovie(movieId);
                        if (movie != null) {
                            System.out.print("新片名: ");
                            String newTitle = scanner.nextLine();
                            System.out.print("新导演: ");
                            String newDirector = scanner.nextLine();
                            System.out.print("新主演(用逗号分隔): ");
                            String[] newStars = scanner.nextLine().split(",");
                            System.out.print("新剧情简介: ");
                            String newDescription = scanner.nextLine();
                            System.out.print("新时长(分钟): ");
                            int newDuration = Integer.parseInt(scanner.nextLine());
                            System.out.print("新评分(0-10): ");
                            double newRating = Double.parseDouble(scanner.nextLine());
                            movie.setTitle(newTitle);
                            movie.setDirector(newDirector);
                            movie.setStars(newStars);
                            movie.setDescription(newDescription);
                            movie.setDuration(newDuration);
                            movie.setRating(newRating);
                            movieManager.updateMovie(movie);
                            System.out.println("影片更新成功");
                        } else {
                            System.out.println("影片不存在");
                        }
                        break;
                    case 4:
                        System.out.print("输入要删除的电影ID: ");
                        String delMovieId = scanner.nextLine();
                        movieManager.deleteMovie(delMovieId);
                        System.out.println("影片删除成功");
                        break;
                    case 5:
                        System.out.print("输入搜索关键词(片名/导演/主演): ");
                        String keyword = scanner.nextLine();
                        List<Movie> searchResults = new ArrayList<>();
                        for (Movie m : movieManager.listAllMovies()) {
                            if (m.getTitle().contains(keyword) || m.getDirector().contains(keyword)) {
                                searchResults.add(m);
                            }
                        }
                        System.out.println("\n搜索结果:");
                        for (Movie m : searchResults) {
                            System.out.println("片名: " + m.getTitle() + ", 导演: " + m.getDirector());
                        }
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }

    private void screeningManagementMenu() {
        while (true) {
            System.out.println("\n--- 排片管理 ---");
            System.out.println("1. 列出所有场次");
            System.out.println("2. 添加场次");
            System.out.println("3. 修改场次");
            System.out.println("4. 删除场次");
            System.out.println("5. 自动排片");
            System.out.println("0. 返回");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        List<Screening> screenings = screeningManager.listAllScreenings();
                        System.out.println("\n场次列表:");
                        for (Screening screening : screenings) {
                            System.out.println("ID: " + screening.getScreeningId() +
                                    ", 片名: " + screening.getMovie().getTitle() +
                                    ", 影厅: " + screening.getHall().getHallName() +
                                    ", 时间: " + screening.getStartTime());
                        }
                        break;
                    case 2:
                        System.out.print("电影ID: ");
                        String movieId = scanner.nextLine();
                        Movie movie = movieManager.getMovie(movieId);
                        if (movie == null) {
                            System.out.println("电影不存在");
                            break;
                        }
                        System.out.print("影厅名称: ");
                        String hallName = scanner.nextLine();
                        ScreeningHall hall = screeningManager.getHall(hallName);
                        if (hall == null) {
                            System.out.println("影厅不存在");
                            break;
                        }
                        System.out.print("开始时间(格式: yyyy-MM-dd HH:mm): ");
                        String timeInput = scanner.nextLine();
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                        LocalDateTime startTime = LocalDateTime.parse(timeInput, formatter);
                        System.out.print("票价: ");
                        double price = Double.parseDouble(scanner.nextLine());
                        screeningManager.addScreening(new Screening(UUID.randomUUID().toString(), movie, hall, startTime, price, false));
                        System.out.println("场次添加成功");
                        break;
                    case 3:
                        System.out.print("输入要修改的场次ID: ");
                        String screeningId = scanner.nextLine();
                        Screening screening = screeningManager.getScreening(screeningId);
                        if (screening != null) {
                            System.out.print("新电影ID: ");
                            String newMovieId = scanner.nextLine();
                            Movie newMovie = movieManager.getMovie(newMovieId);
                            if (newMovie != null) {
                                System.out.print("新影厅名称: ");
                                String newHallName = scanner.nextLine();
                                ScreeningHall newHall = screeningManager.getHall(newHallName);
                                if (newHall == null) {
                                    System.out.println("影厅不存在");
                                    break;
                                }
                                System.out.print("新开始时间(格式: yyyy-MM-dd HH:mm): ");
                                String newTimeInput = scanner.nextLine();
                                formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
                                LocalDateTime newStartTime = LocalDateTime.parse(newTimeInput, formatter);
                                System.out.print("新票价: ");
                                double newPrice = Double.parseDouble(scanner.nextLine());
                                screening.setMovie(newMovie);
                                screening.setHall(newHall);
                                screening.setStartTime(newStartTime);
                                screening.setPrice(newPrice);
                                screeningManager.updateScreening(screening);
                                System.out.println("场次更新成功");
                            } else {
                                System.out.println("新电影不存在");
                            }
                        } else {
                            System.out.println("场次不存在");
                        }
                        break;
                    case 4:
                        System.out.print("输入要删除的场次ID: ");
                        String delScreeningId = scanner.nextLine();
                        screeningManager.deleteScreening(delScreeningId);
                        System.out.println("场次删除成功");
                        break;
                    case 5:
                        System.out.println("自动排片功能将高分电影安排在黄金时段...");
                        // 实现自动排片逻辑
                        System.out.println("自动排片完成!");
                        break;
                    case 0:
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            } catch (DateTimeParseException e) {
                System.out.println("时间格式错误，请使用 yyyy-MM-dd HH:mm");
            }
        }
    }

    private void salesReportMenu() {
        System.out.println("\n--- 销售报表 ---");
        System.out.println("1. 当日销售数据");
        System.out.println("2. 当周销售数据");
        System.out.println("3. 当月销售数据");
        System.out.print("请选择: ");

        try {
            int choice = Integer.parseInt(scanner.nextLine());

            switch (choice) {
                case 1:
                    System.out.println("当日销售数据: ..."); // 实现报表逻辑
                    break;
                case 2:
                    System.out.println("当周销售数据: ..."); // 实现报表逻辑
                    break;
                case 3:
                    System.out.println("当月销售数据: ..."); // 实现报表逻辑
                    break;
                default:
                    System.out.println("无效选择");
            }
        } catch (NumberFormatException e) {
            System.out.println("请输入数字选项");
        }
    }

    private void showFrontDeskMenu() {
        while (true) {
            System.out.println("\n===== 前台菜单 =====");
            System.out.println("1. 列出所有影片");
            System.out.println("2. 列出所有场次");
            System.out.println("3. 查看场次座位");
            System.out.println("4. 售票");
            System.out.println("5. 退票");
            System.out.println("6. 退出登录");
            System.out.print("请选择: ");

            try {
                int choice = Integer.parseInt(scanner.nextLine());

                switch (choice) {
                    case 1:
                        List<Movie> movies = movieManager.listAllMovies();
                        System.out.println("\n影片列表:");
                        for (Movie movie : movies) {
                            System.out.println("ID: " + movie.getMovieId() + ", 片名: " + movie.getTitle() + ", 导演: " + movie.getDirector());
                        }
                        break;
                    case 2:
                        List<Screening> screenings = screeningManager.listAllScreenings();
                        System.out.println("\n场次列表:");
                        for (Screening screening : screenings) {
                            System.out.println("ID: " + screening.getScreeningId() +
                                    ", 片名: " + screening.getMovie().getTitle() +
                                    ", 影厅: " + screening.getHall().getHallName() +
                                    ", 时间: " + screening.getStartTime());
                        }
                        break;
                    case 3:
                        System.out.print("输入场次ID: ");
                        String screeningId = scanner.nextLine();
                        Screening screening = screeningManager.getScreening(screeningId);
                        if (screening != null) {
                            screening.getHall().displaySeatMap();
                        } else {
                            System.out.println("场次不存在");
                        }
                        break;
                    case 4:
                        System.out.print("场次ID: ");
                        String ticketScreeningId = scanner.nextLine();
                        Screening ticketScreening = screeningManager.getScreening(ticketScreeningId);
                        if (ticketScreening != null) {
                            System.out.print("座位信息: ");
                            String seatInfo = scanner.nextLine();
                            System.out.print("是否为儿童票? (y/n): ");
                            boolean isChild = scanner.nextLine().equalsIgnoreCase("y");
                            double price = ticketScreening.getPrice() * (isChild ? 0.5 : 1);
                            Ticket ticket = new Ticket(UUID.randomUUID().toString(), ticketScreening, seatInfo, price);
                            ticketManager.addTicket(ticket);
                            System.out.println("售票成功! 票号: " + ticket.getTicketId());
                            System.out.println("总价: " + ticket.getPrice());
                        } else {
                            System.out.println("场次不存在");
                        }
                        break;
                    case 5:
                        System.out.print("输入票号: ");
                        String ticketId = scanner.nextLine();
                        Ticket ticket = ticketManager.getTicket(ticketId);
                        if (ticket != null && !ticket.isRefunded()) {
                            ticket.setRefunded(true);
                            ticket.setRefundTime(LocalDateTime.now());
                            ticket.setRefundedAmount(ticket.getPrice() * 0.9); // 示例退款逻辑
                            ticketManager.updateTicket(ticket);
                            System.out.println("退票成功! 退款金额: " + ticket.getRefundedAmount());
                        } else {
                            System.out.println("票号无效或已退票");
                        }
                        break;
                    case 6:
                        currentUser = null;
                        return;
                    default:
                        System.out.println("无效选择");
                }
            } catch (NumberFormatException e) {
                System.out.println("请输入数字选项");
            }
        }
    }
}